import os
import sys
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import threading
import pandas as pd
import requests
import json
import configparser
import pathlib

class TianyanchaApp:
    def __init__(self, root):
        self.root = root
        self.root.title("天眼查手机号查询工具")
        self.root.geometry("800x600")
        
        self.file_path = ""
        self.worker_thread = None
        self.stop_flag = False
        
        # 加载配置
        self.config_file = os.path.join(pathlib.Path.home(), '.tianyancha_config.ini')
        self.load_config()
        
        # 创建界面
        self.create_widgets()
        
        # 不再自动检查API状态
        # self.check_api_status()
        
    def load_config(self):
        """加载配置文件，或创建默认配置"""
        self.config = configparser.ConfigParser()
        
        # 默认配置
        self.token = "36f80b34-27c3-40c8-b7a3-018228cb7255"  # 默认token
        
        # 尝试加载已有配置
        if os.path.exists(self.config_file):
            try:
                self.config.read(self.config_file)
                if 'API' in self.config and 'token' in self.config['API']:
                    self.token = self.config['API']['token']
            except Exception as e:
                print(f"加载配置出错: {str(e)}")
                # 使用默认配置
        else:
            # 创建默认配置
            self.config['API'] = {'token': self.token}
            try:
                with open(self.config_file, 'w') as f:
                    self.config.write(f)
            except Exception as e:
                print(f"保存配置出错: {str(e)}")
        
    def save_config(self):
        """保存配置到文件"""
        self.config['API'] = {'token': self.token}
        try:
            with open(self.config_file, 'w') as f:
                self.config.write(f)
        except Exception as e:
            messagebox.showerror("配置保存错误", f"无法保存配置: {str(e)}")
        
    def create_widgets(self):
        # 菜单栏
        menubar = tk.Menu(self.root)
        self.root.config(menu=menubar)
        
        # 设置菜单
        settings_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="设置", menu=settings_menu)
        settings_menu.add_command(label="API设置", command=self.open_settings)
        settings_menu.add_separator()
        settings_menu.add_command(label="关于", command=self.show_about)
        
        # 文件选择区域
        file_frame = tk.Frame(self.root, pady=10)
        file_frame.pack(fill=tk.X, padx=10)
        
        self.file_label = tk.Label(file_frame, text="未选择文件", width=50, anchor="w")
        self.file_label.pack(side=tk.LEFT, padx=(0, 10))
        
        select_file_btn = tk.Button(file_frame, text="选择Excel文件", command=self.select_file)
        select_file_btn.pack(side=tk.RIGHT)
        
        # 进度条
        progress_frame = tk.Frame(self.root, pady=10)
        progress_frame.pack(fill=tk.X, padx=10)
        
        tk.Label(progress_frame, text="处理进度:").pack(side=tk.LEFT)
        self.progress_bar = ttk.Progressbar(progress_frame, orient="horizontal", length=650, mode="determinate")
        self.progress_bar.pack(side=tk.RIGHT, fill=tk.X, expand=True)
        
        # 按钮区域
        btn_frame = tk.Frame(self.root, pady=10)
        btn_frame.pack(fill=tk.X, padx=10)
        
        self.start_btn = tk.Button(btn_frame, text="开始处理", command=self.start_process, state=tk.DISABLED)
        self.start_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        self.stop_btn = tk.Button(btn_frame, text="停止处理", command=self.stop_process, state=tk.DISABLED)
        self.stop_btn.pack(side=tk.LEFT)
        
        # 日志区域
        log_frame = tk.Frame(self.root, pady=10)
        log_frame.pack(fill=tk.BOTH, expand=True, padx=10)
        
        tk.Label(log_frame, text="处理日志:").pack(anchor=tk.W)
        
        log_container = tk.Frame(log_frame, borderwidth=1, relief=tk.SUNKEN)
        log_container.pack(fill=tk.BOTH, expand=True)
        
        self.log_text = tk.Text(log_container, wrap=tk.WORD, state=tk.DISABLED)
        self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        scrollbar = tk.Scrollbar(log_container)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        self.log_text.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.log_text.yview)
    
    def check_api_status(self):
        """检查API令牌状态"""
        status_thread = threading.Thread(target=self._do_check_api_status)
        status_thread.daemon = True
        status_thread.start()
    
    def _do_check_api_status(self):
        """在后台线程中执行API状态检查"""
        try:
            self.add_log("正在检查天眼查API状态...")
            
            # 调用天眼查API进行测试
            url = "https://open.api.tianyancha.com/services/open/search/2.0"
            headers = {
                "Authorization": self.token
            }
            params = {
                "word": "13800138000"  # 使用一个示例手机号进行测试
            }
            
            try:
                response = requests.get(url, params=params, headers=headers, timeout=10)
                
                if response.status_code == 200:
                    data = response.json()
                    if data["error_code"] == 0:
                        self.add_log("API状态正常，令牌有效")
                    else:
                        error_msg = f"API状态异常: {data.get('message', '未知错误')}"
                        self.add_log(error_msg)
                        self.root.after(0, lambda: messagebox.showwarning("API状态异常", 
                                                           f"{error_msg}\n\n错误码: {data.get('error_code', '未知')}\n\n请检查API令牌设置。"))
                elif response.status_code == 401:
                    self.add_log("API认证失败，令牌无效")
                    self.root.after(0, lambda: messagebox.showerror("API认证失败", 
                                                       "天眼查API令牌无效，请检查设置。"))
                else:
                    self.add_log(f"API状态检查失败，HTTP状态码: {response.status_code}")
                    self.root.after(0, lambda: messagebox.showwarning("API状态检查失败", 
                                                       f"无法验证API状态，HTTP状态码: {response.status_code}"))
            except requests.exceptions.ConnectionError:
                self.add_log("网络连接错误，无法连接到天眼查API")
                self.root.after(0, lambda: messagebox.showwarning("网络连接错误", 
                                                   "无法连接到天眼查API，请检查网络连接。"))
            except requests.exceptions.Timeout:
                self.add_log("API状态检查超时")
                self.root.after(0, lambda: messagebox.showwarning("连接超时", 
                                                   "连接天眼查API超时，请检查网络状态。"))
            except Exception as e:
                self.add_log(f"API状态检查出错: {str(e)}")
        except Exception as e:
            print(f"API状态检查异常: {str(e)}")
    
    def open_settings(self):
        """打开设置对话框"""
        settings_window = tk.Toplevel(self.root)
        settings_window.title("API设置")
        settings_window.geometry("400x180")
        settings_window.resizable(False, False)
        settings_window.transient(self.root)
        settings_window.grab_set()
        
        # 设置界面
        frame = tk.Frame(settings_window, padx=20, pady=20)
        frame.pack(fill=tk.BOTH, expand=True)
        
        tk.Label(frame, text="天眼查API令牌:").grid(row=0, column=0, sticky=tk.W, pady=10)
        
        token_entry = tk.Entry(frame, width=30)
        token_entry.grid(row=0, column=1, sticky=tk.W+tk.E, pady=10)
        token_entry.insert(0, self.token)
        
        # API状态测试按钮
        test_btn = tk.Button(frame, text="测试API", 
                           command=lambda: self.test_api_token(token_entry.get()))
        test_btn.grid(row=1, column=0, columnspan=2, pady=5)
        
        # 按钮
        btn_frame = tk.Frame(frame)
        btn_frame.grid(row=2, column=0, columnspan=2, pady=10)
        
        tk.Button(btn_frame, text="保存", command=lambda: self.save_settings(token_entry.get(), settings_window)).pack(side=tk.LEFT, padx=10)
        tk.Button(btn_frame, text="取消", command=settings_window.destroy).pack(side=tk.LEFT, padx=10)
    
    def test_api_token(self, token):
        """测试API令牌有效性"""
        if not token.strip():
            messagebox.showerror("错误", "API令牌不能为空")
            return
            
        try:
            messagebox.showinfo("测试中", "正在测试API令牌，请稍候...")
            
            # 调用天眼查API进行测试
            url = "https://open.api.tianyancha.com/services/open/search/2.0"
            headers = {
                "Authorization": token.strip()
            }
            params = {
                "word": "13800138000"  # 使用一个示例手机号进行测试
            }
            
            try:
                response = requests.get(url, params=params, headers=headers, timeout=10)
                
                if response.status_code == 200:
                    data = response.json()
                    if data["error_code"] == 0:
                        messagebox.showinfo("测试成功", "API令牌有效，连接成功!")
                    else:
                        messagebox.showwarning("API状态异常", 
                                            f"API状态异常: {data.get('message', '未知错误')}\n\n错误码: {data.get('error_code', '未知')}")
                elif response.status_code == 401:
                    messagebox.showerror("认证失败", "API令牌无效，请检查令牌是否正确。")
                else:
                    messagebox.showwarning("测试失败", 
                                        f"API测试失败，HTTP状态码: {response.status_code}")
            except requests.exceptions.ConnectionError:
                messagebox.showerror("网络错误", "无法连接到天眼查API，请检查网络连接。")
            except requests.exceptions.Timeout:
                messagebox.showerror("连接超时", "连接天眼查API超时，请检查网络状态。")
            except Exception as e:
                messagebox.showerror("测试错误", f"API测试出错: {str(e)}")
        except Exception as e:
            messagebox.showerror("测试错误", f"执行API测试时出错: {str(e)}")
    
    def save_settings(self, token, window):
        """保存API设置"""
        if not token.strip():
            messagebox.showerror("错误", "API令牌不能为空")
            return
            
        self.token = token.strip()
        self.save_config()
        messagebox.showinfo("成功", "API设置已保存")
        window.destroy()
    
    def show_about(self):
        """显示关于对话框"""
        messagebox.showinfo("关于", "天眼查手机号查询工具\n\n版本: 1.0\n\n可通过手机号查询关联的企业信息")
    
    def select_file(self):
        file_path = filedialog.askopenfilename(
            title="选择Excel文件",
            filetypes=[("Excel文件", "*.xlsx *.xls")]
        )
        if file_path:
            self.file_path = file_path
            self.file_label.config(text=file_path)
            self.start_btn.config(state=tk.NORMAL)
            self.clear_log()
            self.add_log(f"已选择文件: {file_path}")
    
    def start_process(self):
        if not self.file_path:
            messagebox.showwarning("警告", "请先选择Excel文件")
            return
            
        self.start_btn.config(state=tk.DISABLED)
        self.stop_btn.config(state=tk.NORMAL)
        self.progress_bar["value"] = 0
        self.clear_log()
        self.stop_flag = False
        
        # 创建并启动工作线程
        self.worker_thread = threading.Thread(target=self.process_excel)
        self.worker_thread.daemon = True
        self.worker_thread.start()
        
    def stop_process(self):
        if self.worker_thread and self.worker_thread.is_alive():
            self.stop_flag = True
            self.add_log("正在停止处理...")
        
    def process_excel(self):
        """处理Excel文件并查询天眼查API"""
        try:
            # 读取Excel文件
            df = pd.read_excel(self.file_path)
            if len(df.columns) < 2:
                self.add_log("错误：Excel文件格式不正确，至少需要两列（姓名和手机号）")
                messagebox.showerror("格式错误", "Excel文件格式不正确，至少需要两列（姓名和手机号）")
                self.process_finished("")
                return
                
            # 添加公司名称列
            df['公司名称'] = ''
            
            # 记录匹配的行
            matched_rows = []
            
            # 遍历每一行
            total_rows = len(df)
            for i, row in df.iterrows():
                if self.stop_flag:
                    self.add_log("处理已被用户中断")
                    break
                    
                name = str(row.iloc[0])
                phone = str(row.iloc[1])
                
                # 更新进度
                progress = int((i + 1) / total_rows * 100)
                self.update_progress(progress)
                
                # 检查手机号是否有效
                if not phone or pd.isna(phone) or phone == 'nan':
                    self.add_log(f"跳过第{i+1}行: {name} - 手机号为空")
                    continue
                
                try:
                    # 调用天眼查API
                    url = "https://open.api.tianyancha.com/services/open/search/2.0"
                    headers = {
                        "Authorization": self.token
                    }
                    params = {
                        "word": phone
                    }
                    
                    self.add_log(f"正在查询第{i+1}行: {name} - {phone}")
                    response = requests.get(url, params=params, headers=headers)
                    
                    if response.status_code == 200:
                        data = response.json()
                        if data["error_code"] == 0 and data["result"]["total"] > 0:
                            # 遍历所有结果，找到第一个状态为"存续"的公司
                            company_found = False
                            for item in data["result"]["items"]:
                                if item.get("regStatus") == "存续":
                                    company_name = item["name"]
                                    df.at[i, '公司名称'] = company_name
                                    self.add_log(f"匹配成功: {name} - {phone} -> {company_name}")
                                    matched_rows.append(i)
                                    company_found = True
                                    break  # 找到第一个存续状态的公司就退出循环
                            
                            if not company_found:
                                self.add_log(f"未找到存续状态的公司: {name} - {phone}")
                        elif data["error_code"] == 0:
                            self.add_log(f"未匹配: {name} - {phone}")
                        else:
                            error_msg = f"天眼查API错误: {data.get('reason', '未知错误')}, 错误码: {data.get('error_code', '未知')}"
                            self.add_log(f"{error_msg}, 查询: {name} - {phone}")
                            # 只在第一次遇到API错误时弹窗提示
                            if i == 0:
                                messagebox.showerror("天眼查API错误", f"{error_msg}\n\n请检查您的API令牌是否有效，或者API调用是否超过限额。")
                    elif response.status_code == 401:
                        error_msg = "天眼查API认证失败，请检查您的API令牌是否有效"
                        self.add_log(f"{error_msg}，查询: {name} - {phone}")
                        # 认证错误只提示一次
                        if i == 0:
                            messagebox.showerror("天眼查API认证错误", f"{error_msg}")
                            break
                    elif response.status_code == 429:
                        error_msg = "天眼查API请求频率超限，请稍后再试"
                        self.add_log(f"{error_msg}，查询: {name} - {phone}")
                        # 频率限制错误只提示一次
                        if i == 0:
                            messagebox.showerror("天眼查API频率限制", f"{error_msg}")
                            break
                    else:
                        error_msg = f"API请求失败，状态码: {response.status_code}"
                        self.add_log(f"{error_msg}, 查询: {name} - {phone}")
                        # 只在第一次遇到网络错误时弹窗提示
                        if i == 0:
                            messagebox.showerror("网络请求错误", f"{error_msg}\n\n请检查您的网络连接或天眼查API服务是否正常。")
                except requests.exceptions.ConnectionError:
                    error_msg = "网络连接错误，无法连接到天眼查API"
                    self.add_log(f"{error_msg}，查询: {name} - {phone}")
                    # 网络连接错误只提示一次
                    if i == 0:
                        messagebox.showerror("网络连接错误", f"{error_msg}\n\n请检查您的网络连接并重试。")
                        break
                except requests.exceptions.Timeout:
                    error_msg = "天眼查API请求超时"
                    self.add_log(f"{error_msg}，查询: {name} - {phone}")
                    # 超时错误只提示一次
                    if i == 0:
                        messagebox.showerror("请求超时", f"{error_msg}\n\n请检查您的网络连接并重试。")
                except Exception as e:
                    self.add_log(f"查询出错: {name} - {phone}, 错误: {str(e)}")
                    # 只在第一次遇到未知错误时弹窗提示
                    if i == 0:
                        messagebox.showerror("查询错误", f"在查询过程中遇到错误: {str(e)}\n\n请检查您的输入数据是否正确。")
            
            # 只保留匹配到的行
            output_path = ""
            if matched_rows and not self.stop_flag:
                matched_df = df.iloc[matched_rows]
                
                # 生成输出文件名
                base_name = os.path.splitext(os.path.basename(self.file_path))[0]
                output_path = os.path.join(os.path.dirname(self.file_path), f"{base_name}_结果.xlsx")
                
                # 导出结果
                matched_df.to_excel(output_path, index=False)
                self.add_log(f"已将匹配结果保存至: {output_path}")
            elif not self.stop_flag:
                self.add_log("没有找到匹配的记录")
                
            self.process_finished(output_path)
                
        except pd.errors.EmptyDataError:
            error_msg = "Excel文件为空或格式不正确"
            self.add_log(f"处理文件时出错: {error_msg}")
            messagebox.showerror("文件错误", error_msg)
            self.process_finished("")
        except pd.errors.ParserError:
            error_msg = "无法解析Excel文件，请确保文件格式正确"
            self.add_log(f"处理文件时出错: {error_msg}")
            messagebox.showerror("解析错误", error_msg)
            self.process_finished("")
        except Exception as e:
            error_msg = f"处理文件时出错: {str(e)}"
            self.add_log(error_msg)
            messagebox.showerror("处理错误", f"处理文件时发生错误:\n{str(e)}")
            self.process_finished("")
    
    def update_progress(self, value):
        # 在主线程中更新UI
        self.root.after(0, lambda: self.progress_bar.configure(value=value))
    
    def add_log(self, message):
        # 在主线程中更新UI
        self.root.after(0, lambda: self._append_to_log(message))
    
    def _append_to_log(self, message):
        self.log_text.config(state=tk.NORMAL)
        self.log_text.insert(tk.END, message + "\n")
        self.log_text.see(tk.END)
        self.log_text.config(state=tk.DISABLED)
    
    def clear_log(self):
        self.log_text.config(state=tk.NORMAL)
        self.log_text.delete(1.0, tk.END)
        self.log_text.config(state=tk.DISABLED)
    
    def process_finished(self, output_path):
        # 在主线程中更新UI
        self.root.after(0, lambda: self._on_process_finished(output_path))
    
    def _on_process_finished(self, output_path):
        self.start_btn.config(state=tk.NORMAL)
        self.stop_btn.config(state=tk.DISABLED)
        
        if output_path:
            self.add_log("处理完成!")
            answer = messagebox.askyesno("处理完成", 
                                      f"处理已完成，是否打开结果文件？\n{output_path}")
            if answer:
                # 尝试打开结果文件
                try:
                    if sys.platform == 'darwin':  # macOS
                        os.system(f"open '{output_path}'")
                    elif sys.platform == 'win32':  # Windows
                        os.system(f'start excel "{output_path}"')
                    else:  # Linux
                        os.system(f"xdg-open '{output_path}'")
                except Exception as e:
                    messagebox.showwarning("警告", f"无法打开文件: {str(e)}")
        else:
            self.add_log("处理完成，但没有生成结果文件。")

def main():
    root = tk.Tk()
    app = TianyanchaApp(root)
    root.mainloop()

if __name__ == "__main__":
    main() 